//MountManager - the program for easy mounting of storage devices in Linux
//Copyright (C) 2007-2008 Tikhonov Sergey
//
//This file is part of MountManager Gui
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#include <QtGui/QSplitter>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QDockWidget>
#include <QtGui/QListWidget>
#include <QtGui/QToolBar>
#include <QtGui/QMenu>
#include <QtCore/QDir>
#include <QtCore/QSettings>
#include <QtCore/QUrl>
#include <QtCore/QPluginLoader>
#include <QDebug>
#include "pluginsmanager.h"
#include "plugininterface.h"
#include "const.h"

PluginsManager::PluginsManager(QWidget *parent) : QDialog(parent) {
	pluginLoader = new QPluginLoader(parent);
	
	splitter = new QSplitter;
	
	listWidget = new QListWidget;
	connect(listWidget,SIGNAL(currentItemChanged(QListWidgetItem *,QListWidgetItem*)),
		   		this,SLOT(currentItemChangedSlot(QListWidgetItem *,QListWidgetItem *)));
	
	rightWidget = new QWidget;
	
	headerLabel = new QLabel;
	
	descriptionLabel = new QLabel;
	descriptionLabel->setWordWrap(true);
	descriptionLabel->setAlignment(Qt::AlignTop);
	
	enableButton = new QPushButton(tr("Enable"));
	enableButton->setIcon(QIcon(ICONS_PATH"enable.png"));
	enableButton->setEnabled(false);
	connect(enableButton,SIGNAL(clicked()),this,SLOT(enablePlugin()));
	
	disableButton = new QPushButton(tr("Disable"));
	disableButton->setIcon(QIcon(ICONS_PATH"cancel.png"));
	disableButton->setEnabled(false);
	connect(disableButton,SIGNAL(clicked()),this,SLOT(disablePlugin()));
	
	showButton = new QPushButton(tr("Show"));
	showButton->setEnabled(false);
	connect(showButton,SIGNAL(clicked()),this,SLOT(showPlugin()));

	QHBoxLayout *topLayout = new QHBoxLayout;
	topLayout->addWidget(enableButton);
	topLayout->addWidget(disableButton);
	topLayout->addWidget(showButton);
	topLayout->addStretch();

	QVBoxLayout *rightWidgetLayout = new QVBoxLayout;
	rightWidgetLayout->addWidget(headerLabel);
	rightWidgetLayout->addWidget(descriptionLabel,1);
	rightWidget->setLayout(rightWidgetLayout);
	
	splitter->addWidget(listWidget);
	splitter->addWidget(rightWidget);
	splitter->setStretchFactor(1,1);
	splitter->setCollapsible(0,false);
	splitter->setCollapsible(1,false);
	
	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->addLayout(topLayout);
	mainLayout->addWidget(splitter);
	setLayout(mainLayout);

	setWindowTitle(tr("Plugins manager"));

	update();
	resize(600,300);
}

PluginsManager::~PluginsManager() {
	delete enableButton;
	delete disableButton;
	delete showButton;
	delete pluginLoader;
	delete listWidget;
	delete headerLabel;
	delete descriptionLabel;
	delete rightWidget;
	delete splitter;
}

void PluginsManager::update() {
	QSettings settings(ORGANIZATION,PROGRAM_NAME);
	settings.beginGroup("Plugins");
	
	// Scan plugins directory and load available plugins, append them to the list pluginsList
	QDir pluginsDir(PLUGINS_PATH);
	foreach (QString pluginName,pluginsDir.entryList(QDir::Files)) {
		if (!settings.contains(pluginName)) {
			pluginLoader->setFileName(pluginsDir.absoluteFilePath(pluginName));
			if (MountManagerPlugin *plugin = qobject_cast<MountManagerPlugin *>(pluginLoader->instance())) {
				QListWidgetItem *newItem = new QListWidgetItem;
				newItem->setText(plugin->pluginName());
				QString pluginTypesString;
				if (plugin->dialog() != 0)
					pluginTypesString += ',' + tr("dialog");
				if (plugin->dockWidget() != 0)
					pluginTypesString += ',' + tr("panel");
				if (plugin->menu() != 0)
					pluginTypesString += ',' + tr("menu");
				if (plugin->toolBar() != 0)
					pluginTypesString += ',' + tr("tool bar");
				pluginTypesString.remove(0,1);
				newItem->setData(PluginType,pluginTypesString);
				newItem->setData(PluginDescription,plugin->pluginDescription());
				newItem->setData(PluginFileName,pluginName);
				listWidget->addItem(newItem);
				pluginsList.append(plugin);
				enablePlugin(newItem);
			} else
				qDebug() << QString("Plugin with file name: %1 is invalid.").arg(pluginName);
		}
		else {
			QStringList data;
			data = settings.value(pluginName).toStringList();
			if (data.count() != 5)
				continue;
			QListWidgetItem *newItem = new QListWidgetItem;
			newItem->setText(data[1]);
			newItem->setData(PluginType,data[2]);
			newItem->setData(PluginDescription,data[3]);
			newItem->setData(PluginFileName,data[0]);
			newItem->setData(PluginEnabled,data[4]);
			listWidget->addItem(newItem);
			if (data[4] == "true") {
				pluginLoader->setFileName(QString(PLUGINS_PATH) + data[0]);
				if (MountManagerPlugin *plugin = qobject_cast<MountManagerPlugin *>(pluginLoader->instance())) {
					pluginsList.append(plugin);
				}
				enablePlugin(newItem);
			} else {
				MountManagerPlugin *plugin = 0;
				pluginsList.append(plugin);
				newItem->setIcon(QIcon(ICONS_PATH"cancel.png"));
			}
		}
	}

	if (pluginsList.isEmpty())
		headerLabel->setText("<center><b>" + tr("There are no plugins") + "</b></center>");
	listWidget->setCurrentRow(0);
	
	settings.endGroup();
}

void PluginsManager::currentItemChangedSlot(QListWidgetItem *currentItem,QListWidgetItem *previousItem) {
	if (currentItem == 0)
		currentItem = previousItem;
	if (currentItem == 0)
		return;
	showButton->setEnabled(true);
	if (currentItem->data(PluginEnabled).toBool()) {
		enableButton->setEnabled(false);
		disableButton->setEnabled(true);
	} else {
		enableButton->setEnabled(true);
		disableButton->setEnabled(false);
	}
	
	headerLabel->setText("<center><b>" + currentItem->text() + "</b></center>");
	descriptionLabel->setText("<b>" + tr("Type") + ":</b> " + currentItem->data(PluginType).toString()
						 + "<br><b>" + tr("Description") + ":</b> " + currentItem->data(PluginDescription).toString());
}

QList<MountManagerPlugin *>& PluginsManager::plugins() {
	return pluginsList;
}

void PluginsManager::saveSettings() {
	QSettings settings(ORGANIZATION,PROGRAM_NAME);
	settings.beginGroup("Plugins");
	int count = listWidget->count();
	for (int i = count-1; i >= 0; i--) {
		QListWidgetItem *item = listWidget->item(i);
		QStringList data;
		data << item->data(PluginFileName).toString() << item->text() << item->data(PluginType).toString() << item->data(PluginDescription).toString() << item->data(PluginEnabled).toString();
		settings.setValue(item->data(PluginFileName).toString(),data);
	}
	settings.endGroup();
}

void PluginsManager::enablePlugin(QListWidgetItem *item) {
	if (item == 0)
		item = listWidget->currentItem();
	// if plugin wasn't loaded yet
	if (pluginsList[listWidget->row(item)] == 0) {
		pluginLoader->setFileName(QString(PLUGINS_PATH) + item->data(PluginFileName).toString());
		pluginsList[listWidget->row(item)] = qobject_cast<MountManagerPlugin *>(pluginLoader->instance());
	}
	item->setData(PluginEnabled,true);
	item->setIcon(QIcon(ICONS_PATH"enable.png"));
	currentItemChangedSlot(item,0);
	emit (pluginEnabled(listWidget->row(item)));
}

void PluginsManager::disablePlugin() {
	QListWidgetItem *item = listWidget->currentItem();
	item->setData(PluginEnabled,false);
	item->setIcon(QIcon(ICONS_PATH"cancel.png"));
	currentItemChangedSlot(item,0);
	emit (pluginDisabled(listWidget->row(item)));
}

void PluginsManager::showPlugin() {
	QListWidgetItem *item = listWidget->currentItem();
	if (!item->data(PluginEnabled).toBool())
		enablePlugin(item);
	MountManagerPlugin *plugin = pluginsList[listWidget->row(item)];
	if (plugin->dialog() != 0)
		plugin->dialog()->show();
	if (plugin->dockWidget() != 0)
		plugin->dockWidget()->show();
	if (plugin->menu() != 0)
		plugin->menu()->show();
	if (plugin->toolBar() != 0)
		plugin->toolBar()->show();
}

bool PluginsManager::isPluginEnabled(MountManagerPlugin *plugin) {
	QListWidgetItem *item = listWidget->item(pluginsList.indexOf(plugin));
	return item->data(PluginEnabled).toBool();
}
